package apps

import (
	"fmt"
	"gitee.com/zhangyu520cw/restful-api-demo-g7/apps/host"
	"github.com/gin-gonic/gin"
)

//IOC 容器层： 管理所有的服务的实例对象

// 1. HostService的实例必须注册过来，HostService 才会有具体的实例, 服务启动时注册
// 2. HTTP 暴漏模块，依赖Ioc里面的HostService
var (
	// 使用interface{} + 断言进行抽像
	HostService host.Service // 写40个定义

	// 维护当前所有的服务
	implApps = map[string]ImplService{}
	ginApps  = map[string]GinService{}
)

func RegistryImpl(svc ImplService) {
	// 服务实例注册到svcs map 当中
	if _, ok := implApps[svc.Name()]; ok {
		panic(fmt.Sprintf("ImplService %s has been registered", svc.Name()))
	}
	implApps[svc.Name()] = svc
	// 根据对象满足的接口来注册具体的服务
	if v, ok := svc.(host.Service); ok {
		HostService = v
	}
}
func RegistryGin(svc GinService) {
	if _, ok := ginApps[svc.Name()]; ok {
		panic(fmt.Sprintf("GinService %s has been registered", svc.Name()))
	}
	// 不用对外暴漏，统一维护
	ginApps[svc.Name()] = svc
}

// 用户初始化注册到Ioc容器里面的所有服务
func InitImpl() {
	for _, v := range implApps {
		v.Config()
	}
}

func InitGin(r gin.IRouter) {
	// 先初始化好所有的对象
	for _, v := range ginApps {
		v.Config()
	}

	for _, v := range ginApps {
		v.Registry(r)
	}
}

// 已经加载完成的Gin App有哪些
func LoadedGinApps() (names []string) {
	for k := range ginApps {
		names = append(names, k)
	}
	return names
}

type ImplService interface {
	Config()
	Name() string
}

// 如果指定了具体类型，就导致每增加一种类型，多一个get方法。
// Get 一个Impl的实例
// 返回一个对象，任何类型都可以，使用时，由使用方进行断言
func GetImpl(name string) interface{} {
	for k, v := range implApps {
		if k == name {
			return v
		}
	}

	return nil
}

// 注册由gin编写的handler
// 编写 编写了Http服务A ，只需要实现Registry方法
type GinService interface {
	Registry(r gin.IRouter)
	Config()
	Name() string
}
